﻿// Copyright Maxime Serrano <lastchronicler@gmail.com>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ForgeCraft {
    public class Entity {

    public Position pos;
    public Position lastpos;
    public World inWorld;
    public bool isRidable;
    public int id = -1;
    public Velocity velocity;

    public bool Spawned;

    public Chunk CurrentChunk;
    //short type;
    //short damage;



    public Entity()
        {
            CurrentChunk = null;
            id = Server.GetNextID();
            isRidable = true;
            velocity = new Velocity(0, 0, 0);

        //Server.random.Next();
        }

        virtual public void Knockback(float direction)
        {
            // This should knock things back, but it risks moving them into blocks??

            float kdir;

            if (direction > 0) kdir = direction - 128;
            else kdir = direction + 127;

            pos.y += 1.5;

            if (kdir < -111 || kdir > 112) // East
            {
                pos.z += 1.5;
            }
            else if (kdir < -79) // SouthEast
            {
                pos.x -= 1.5;
                pos.z += 1.5;
            }
            else if (kdir > 80) // NorthEast
            {
                pos.x += 1.5;
                pos.z += 1.5;   
            }
            else if (kdir < -47) // South
            {
                pos.x -= 1.5;
            }
            else if (kdir > 48) // North
            {
                pos.x += 1.5;
            }
            else if (kdir > 16) // NorthWest
            {
                pos.x += 1.5;
                pos.z -= 1.5;
            }
            else if (kdir < -15) // SouthWest
            {
                pos.x -= 1.5;
                pos.z -= 1.5;
            }
            else // West
            {
                pos.z -= 1.5;
            }
        }

        virtual public void Update()
        {
            if (!Spawned) return;

            Chunk oldChunk = CurrentChunk;
            Chunk newChunk = inWorld.GetChunk((int)((int)pos.x / 16), (int)((int)pos.z / 16));
            if (oldChunk != newChunk)
            {
                if (oldChunk != null) oldChunk.Entities.Remove(this);
                newChunk.Entities.Add(this);
                CurrentChunk = newChunk;
            }

            double dx = pos.x - lastpos.x, dy = pos.y - lastpos.y, dz = pos.z - lastpos.z;
            bool rotchanged = (pos.rotation != lastpos.rotation || pos.pitch != lastpos.pitch);
            lastpos.x = pos.x; lastpos.y = pos.y; lastpos.z = pos.z;
            lastpos.rotation = pos.rotation; lastpos.pitch = pos.pitch;

            bool sendVel = false;

            if (velocity.x != 0) { velocity.x += -1343; sendVel = true; }
            if (velocity.y != 0) {velocity.y += -1343; sendVel = true; }
            if (velocity.z != 0) {velocity.z += -1343; sendVel = true; }

            if (dx != 0 || dy != 0 || dz != 0 || rotchanged || sendVel)
            {
                foreach (Player p in inWorld.playerList)
                {
                    if (p != this)
                    {
                        if (inWorld.IsInPlayersChunk(p, this.pos))
                        {
                            p.UpdateEntity(this, dx, dy, dz, rotchanged, false, sendVel);
                        }
                    }   
                }
            }
        }

        virtual public void Despawn()
        {
            if (CurrentChunk != null)
            {
                CurrentChunk.Entities.Remove(this);
                CurrentChunk = null;
               
            }

            Spawned = false;
        }

        override public string ToString()
        {
            return "[Entity " + id + "]";
        }
    }
}
